﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data;
using System.Text;

namespace Shapefile
{
    static class ShapeFactory
    {
        public static ESRIShape ParseShape(byte[] shapeData, StringDictionary metaData, IDataRecord dataRecord)
        {
            if (shapeData == null)
            {
                throw new ArgumentNullException("ShapeData is Null!");
            }

            if (shapeData.Length < 12)
            {
                throw new ArgumentException("shapeData must be at least 12 bytes long");
            }

            /*
                Position  Field           Value                   Type        Order
                Byte 0    Record          Number Record Number    Integer     Big
                Byte 4    Content Length  Content Length          Integer     Big

                Position  Field       Value                   Type        Number      Order
                Byte 0    Shape Type  Shape Type              Integer     1           Little
            */

            int recordNumber = BinaryConverter.ToInt32(shapeData, 0, ByteOrder.Big);
            int contentLengthInWords = BinaryConverter.ToInt32(shapeData, 4, ByteOrder.Big);

            ShapeType shapeType = (ShapeType)BinaryConverter.ToInt32(shapeData, 8, ByteOrder.Little);

            if (shapeData.Length != (contentLengthInWords * 2) + 8)
            {
                throw new InvalidOperationException("Shape data length does not match shape header length");
            }

            ESRIShape shape = null;

            switch (shapeType)
            {
                case ShapeType.Null:
                    shape = new ESRIShape(shapeType, recordNumber, metaData, dataRecord);
                    break;
                case ShapeType.Point:
                    shape = new ESRIPoint(recordNumber, metaData, dataRecord, shapeData);
                    break;
                case ShapeType.PolyLine:
                    shape = new ESRIPolyLine(recordNumber, metaData, dataRecord, shapeData);
                    break;
                case ShapeType.Polygon:
                    shape = new ESRIPolygon(recordNumber, metaData, dataRecord, shapeData);
                    break;

                default:
                    throw new NotImplementedException(string.Format("Shapetype {0} is not implemented", shapeType));
            }

            return shape;
        }
    }
}
